/**
 * 
 */
package com.designpattern.design.command;

/**
 * 命令模式设计-完成智能家电项目
 * @author zhangyang
 *
 */
public class CommandTest {
public static void main(String[] args) {
	//传入电灯接收者
	LightReceiver lightReceiver = new LightReceiver();
	
	//构建电灯开关命令
	LinghtOnCommand onCommand1 = new LinghtOnCommand(lightReceiver);
	LinghtOffCommand offCommand1 = new LinghtOffCommand(lightReceiver);
	//构建一个命令发起者
	Controller controller = new Controller();
	//将电灯开关绑定命令命令发起者
	controller.setCommand(0, onCommand1, offCommand1);
	System.out.println("-----执行电灯打开命令------");
	controller.setOnButton(0);
	System.out.println("-----撤销命令------");
	controller.setCallBackButton();
	System.out.println("-----再次执行电灯打开命令------");
	controller.setOnButton(0);
	System.out.println("-----执行电灯关闭命令------");
	controller.setOffButton(0);
	System.out.println("-----撤销命令------");
	controller.setCallBackButton();
	/**
	 * 需求扩展-添加电视开关进入遥控器
	 */
	//新增电视接收者
	TVReceiver tvReceiver = new TVReceiver();
	//新增电视打开关闭命令
	TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);
	TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);
	//将电视开关添加到控制器 设置下标1
	controller.setCommand(1, tvOnCommand, tvOffCommand);
	//开始使用
	System.out.println("=====电视机打开===");
	controller.setOnButton(1);
	System.out.println("=====电视机关闭===");
	controller.setOffButton(1);
	System.out.println("=====撤销命令=====");
	controller.setCallBackButton();
}
}

/**
 * 命令执行者
 * @author zhangyang
 *
 */
class LightReceiver{
	public void on() {
		System.out.println("电灯打开");
	}
	public void off() {
		System.out.println("电灯关闭");
	}
}
/**
 * 命令接口 实现命令和撤销命令
 * @author zhangyang
 *
 */
interface Command{
	//执行命令
	void execute();
	//撤销命令
	void undo();
}

/**
 * 电灯打开命令
 * @author zhangyang
 *
 */
class LinghtOnCommand implements Command{

	/**
	 * 将命令执行者聚合进来
	 */
	LightReceiver  light;
	
	
	public LinghtOnCommand(LightReceiver light) {
		super();
		this.light = light;
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		light.on();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		light.off();
	}
	
}

/**
 * 电灯关闭命令
 * @author zhangyang
 *
 */
class LinghtOffCommand implements Command{

	/**
	 * 将命令执行者聚合进来
	 */
	LightReceiver  light;
	
	
	public LinghtOffCommand(LightReceiver light) {
		super();
		this.light = light;
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		light.off();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		light.on();
	}
	
}

/**
 * 空操作-没有任何命令 空执行 用于初始化
 * 当调用空命令 什么也不做-这也是一种设计模式 省略对空的判断
 * @author zhangyang
 *
 */
class NoCommand implements Command{

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		System.out.println("初始化无命令");
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		System.out.println("初始化undo无命令");
	}
	
}

/**
 * 命令发起者-聚合很多很多的命令
 * @author zhangyang
 *
 */
class Controller{
	//打开命令
	Command[] onCommands;
	//关闭命令
	Command[] offCommands;
	//撤销命令-用于记录上一次执行的操作
	Command undoCommand;
	public Controller() {
		super();
		//初始化5个命令组
		onCommands=new Command[5];
		offCommands=new Command[5];
		for(int i=0;i<5;i++) {
			//开关操作都设置为空命令
			onCommands[i]=new NoCommand();
			offCommands[i]=new NoCommand();
		}
	}
	/**
	 * 给按钮设置你需要的命令 
	 * 将对应的电器元件绑定到指定的下标上
	 * @param index
	 * @param onCommand
	 * @param offCommand
	 */
	public void setCommand(int index,Command onCommand,Command offCommand) {
		onCommands[index]=onCommand;
		offCommands[index]=offCommand;
	}
	//打开按钮设置 传入指定的下标打开对应
	public void setOnButton(int index) {
		this.onCommands[index].execute();
		//记录上一次操作
		this.undoCommand=this.onCommands[index];
	}
	
	public void setOffButton(int index) {
		this.offCommands[index].execute();
		//记录上一次操作
		this.undoCommand=this.offCommands[index];
	}
	public void setCallBackButton() {
		this.undoCommand.undo();
	}
}

/**
 * 应用扩展-电视加入遥控器
 * 电视接收者
 * @author zhangyang
 *
 */
class TVReceiver{
	public void on() {
		System.out.println("电视打开");
	}
	public void off() {
		System.out.println("电视关闭");
	}
}

/**
 * 电视打开命令
 * @author zhangyang
 *
 */
class TVOnCommand implements Command{

	TVReceiver receiver;
	
	
	public TVOnCommand(TVReceiver receiver) {
		super();
		this.receiver = receiver;
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		receiver.on();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		receiver.off();
	}
	
}

/**
 * 电视关闭命令
 * @author zhangyang
 *
 */
class TVOffCommand implements Command{

	TVReceiver receiver;
	
	
	public TVOffCommand(TVReceiver receiver) {
		super();
		this.receiver = receiver;
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		receiver.off();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		receiver.on();
	}
	
}